/**
 * @export
 * @class Text
 * @classdesc 文本组件
 * @property {Object} 地图容器 - SchoolLab实例
 * @property {String} name - 名称
 * @property {String} color - 颜色
 * @property {Number} opacity - 透明度
 * @property {String} text - 文本
 * @property {Boolean} outline - 是否有外轮廓
 * @property {String} outlineColor - 外轮廓颜色
 * @property {Number} renderOrder - 层叠顺序
 * @property {Number} fontSize - 字号大小
 * @property {Number} padding - 文字离边框间隔
 * @property {Boolean} background - 是否有背景
 * @property {String} backgroundColor - 背景颜色
 * @property {Boolean} sizeAttenuation - 是否自适应尺寸
 * @property {Number} height - 文本高度
 * @example
 * var text = new Text(viewer, {
 *   height: 14,
 *   color: '#ff0000',
 *   opacity: 0.5,
 *   renderOrder: 20,
 *   name: 'text'
 * })
 */
import { extend, hexToRGB, lngLatToWorld, transformCoordinate } from './util'
import Feature from './Feature'
export default class Text {
  constructor(viewer, options) {
    const opts = extend({
      name: "text",
      color: "#ffffff",
      opacity: 1,
      renderOrder: 1,
      text: '',
      outline: false,
      outlineColor: '#ff0000',
      fontSize: 128,
      lineWidth: 2,
      padding: 15,
      background: true,
      backgroundColor: '#000000',
      sizeAttenuation: true,
      height: 1
    }, options)

    /** @member {SchoolLab} - 地图容器 */
    this.viewer = viewer
    
    /** @member {String} - 名称 */
    this.name = opts.name
    
    /** @member {Color} - 颜色 */
    this.color = opts.color
    
    /** @member {Number} - 透明度 */
    this.opacity = opts.opacity
    
    /** @member {Number} - 层叠顺序 */
    this.renderOrder = opts.renderOrder
    
    /** @member {String} - 文本标题 */
    this.text = opts.text
    
    /** @member {Boolean} - 是否有外轮廓 */
    this.outline = opts.outline
    
    /** @member {String} - 外轮廓宽度 */
    this.lineWidth = opts.lineWidth
    
    /** @member {Number} - 字号大小 */
    this.fontSize = opts.fontSize
    
    /** @member {Number} - 间隙尺寸 */
    this.padding = opts.padding
    
    /** @member {String} - 外轮廓颜色 */
    this.outlineColor = opts.outlineColor
    
    /** @member {Boolean} - 是否包含背景 */
    this.background = opts.background
    
    /** @member {String} - 背景颜色 */
    this.backgroundColor = opts.backgroundColor
    
    /** @member {Number} - 文本高度 */
    this.height = opts.height
    
    /** @member {Boolean} - 是否自适应大小 */
    this.sizeAttenuation = opts.sizeAttenuation
    
    /** @member {THREE.Mesh} - mesh对象 */
    this.entity = null

    Feature.apply(this)

    this._init()
  }

  // 初始化组件
  _init() {
    let canvas = this._initCanvas()

    const image = canvas.toDataURL()
    const loader = new THREE.TextureLoader()
    const map = loader.load(image)
    map.wrapS = map.wrapT = THREE.RepeatWrapping
    const material = new THREE.SpriteMaterial({
      map: map,
      blending: THREE.NormalBlending
    })
    const mesh = new THREE.Sprite(material)
    mesh.material.sizeAttenuation = this.sizeAttenuation
    mesh.name = this.name
    mesh.renderOrder = this.renderOrder
    mesh.visible = false

    if (this.sizeAttenuation) {
      mesh.scale.set(this.height / canvas.height * canvas.width, this.height, 1)
    } else {
      mesh.scale.set(this.height / canvas.height * canvas.width / this.viewer.box.clientHeight, this.height / this.viewer.box.clientHeight, 1)
    }

    this.entity = mesh
    this.viewer.world.add(mesh)
    canvas = null
  }

  // 初始化canvas
  _initCanvas() {
    const canvas = document.createElement('canvas')

    const fontSize = this.fontSize
    const padding = this.padding

    const context = canvas.getContext('2d')

    context.font = `${fontSize}px "Microsoft YaHei"`

    const width = context.measureText(this.text).width
    // const width2 = CanvasUtil.makePowerOfTwo(width + padding * 2)
    // const height2 = CanvasUtil.makePowerOfTwo(fontSize + padding * 2)
    const width2 = Math.ceil(width + padding * 8)
    const height2 = Math.ceil(fontSize + padding * 4)

    canvas.width = width2
    canvas.height = height2

    if (this.background) {
      context.fillStyle = this.backgroundColor
      context.fillRect(0, 0, width2, height2)
    }

    // 设置样式并绘制文字
    context.imageSmoothingQuality = 'high'
    context.textBaseline = 'middle'
    context.textAlign = 'center'
    context.lineWidth = this.lineWidth

    const halfWidth = width2 / 2
    const halfHeight = height2 / 2

    // 画描边
    context.font = `bold ${fontSize}px "Microsoft YaHei"`
    if (this.outline) {
      context.lineWidth = this.lineWidth
      context.strokeStyle = this.outlineColor
      context.strokeText(this.text, halfWidth, halfHeight)
    }

    // 画文字
    context.fillStyle = this.color
    // 设置文字阴影的颜色为黑色，透明度为20%
    const color1 = hexToRGB(this.color)
    context.shadowColor = `rgba(${color1.r}, ${color1.g}, ${color1.b}, 0.3)`
    // 将阴影向右移动15px，向上移动10px
    context.shadowOffsetX = 0
    context.shadowOffsetY = 0
    // 轻微模糊阴影
    context.shadowBlur = 6

    context.fillText(this.text, halfWidth, halfHeight * 1.1)

    return canvas
  }

  // 修改文本
  setText(text) {
    this.text = text
    let canvas = this._initCanvas()
    const image = canvas.toDataURL()
    const loader = new THREE.TextureLoader()
    const map = loader.load(image)
    map.wrapS = map.wrapT = THREE.RepeatWrapping

    this.entity.material.map = map
    this.entity.material.map.needsUpdate = true
  }

  // 设置经纬度坐标
  setGisPosition(lngLat, altitude) {
    this.entity.visible = false
    let world = lngLatToWorld(lngLat)
    let format = transformCoordinate(this.viewer.gisCenter, world)
    this.entity.position.set(format.x, format.y, altitude)
    this.entity.visible = true
  }

  // 设置世界相对坐标
  setPosition(vec2, altitude) {
    this.entity.visible = false
    this.entity.position.set(vec2.x, vec2.y, altitude)
    this.entity.visible = true
  }

  // 显示
  show() {
    this.entity.visible = true
  }

  // 隐藏
  hide() {
    this.entity.visible = false
  }

  // 组件销毁
  destroy() {
    this._disposeHierarchy(this.entity, this._dispose)
    this.viewer.world.remove(this.entity)
    this.entity = null
  }
}
